import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_lui/flutter_lui.dart';
import 'package:flutter_lui/src/l_style.dart';

enum LSwitchShape {
  /// 圆形
  circle,

  /// 方形
  square,
}

class LSwitch extends StatefulWidget {
  /// 当前状态
  final bool? value;

  /// 值改变时的回调
  final Function(bool)? onChange;

  /// 类型 根据类型显示颜色 优先级没有color高
  final LUIType? type;

  /// 颜色
  final Color? color;

  /// 形状
  final LSwitchShape shape;

  /// 宽度
  final double? width;

  /// 高度
  final double? height;

  /// 打开时文字
  final String? activeText;

  /// 关闭时文字
  final String? inactiveText;

  /// 圆角
  final double? borderRadius;

  /// 是否禁用
  final bool? disabled;

  /// 外边距
  /// - [1]=>all
  /// - [1,1]=>[上下，右左]
  /// - [1,1,1]=> [上，右左，下]
  /// - [1,1,1,1]=> [上，右，下，左]
  final List<double> margin;

  /// 左外边距
  final double? marginLeft;

  /// 右外边距
  final double? marginRight;

  /// 上外边距
  final double? marginTop;

  /// 下外边距
  final double? marginBottom;

  /// 上下外边距
  final double? marginVertical;

  /// 左右外边距
  final double? marginHorizontal;
  const LSwitch(
      {this.value,
      this.onChange,
      this.type = LUIType.primary,
      this.color,
      this.shape = LSwitchShape.circle,
      this.width,
      this.height,
      this.activeText,
      this.inactiveText,
      this.borderRadius,
      this.disabled,
      this.margin = const [0],
      this.marginLeft,
      this.marginRight,
      this.marginTop,
      this.marginBottom,
      this.marginVertical,
      this.marginHorizontal,
      Key? key})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _LSwitch();
}

class _LSwitch extends State<LSwitch> with TickerProviderStateMixin {
  final usePadding = lrpx(2);
  late AnimationController bgController;
  late Animation<double> bgAnimation;
  late AnimationController activeController;
  double useLeft = 0;
  late double useWidth;
  late double useHeight;
  @override
  void initState() {
    super.initState();
    useWidth = widget.width ?? lrpx(50);
    useHeight = widget.height ?? lrpx(24);
    bgController = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 100));
    bgAnimation = Tween<double>(begin: 0, end: 1).animate(
        CurvedAnimation(parent: bgController, curve: Curves.bounceOut));

    var maxMove = useWidth - useHeight;
    activeController = AnimationController(
        lowerBound: 0,
        upperBound: maxMove,
        vsync: this,
        duration: const Duration(milliseconds: 100));
    activeController.addListener(() {
      setState(() {
        useLeft = activeController.value;
      });
    });
    valueAnimation();
  }

  @override
  void didUpdateWidget(LSwitch oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.width != widget.width || oldWidget.height != widget.height) {
      var maxMove = useWidth - useHeight;
      activeController.dispose();
      activeController = AnimationController(
          lowerBound: 0,
          upperBound: maxMove,
          vsync: this,
          duration: const Duration(milliseconds: 100));
      activeController.addListener(() {
        setState(() {
          useLeft = activeController.value;
        });
      });
    }
    if (widget.value == true) {
      bgController.forward();
      activeController.forward();
    } else {
      bgController.reverse();
      activeController.reverse();
    }
  }

  valueAnimation() {
    if (widget.value != true) {
      bgController.reverse();
      activeController.reverse();
    } else {
      bgController.forward();
      activeController.forward();
    }
  }

  handleTap() {
    if (widget.disabled == true) return;
    valueAnimation();
    if (widget.onChange != null) {
      widget.onChange!(widget.value == false);
    }
  }

  @override
  void dispose() {
    activeController.dispose();
    bgController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    var useColor = widget.color ??
        (widget.type == LUIType.danger
            ? LUI.instance.dangerColor
            : widget.type == LUIType.success
                ? LUI.instance.successColor
                : widget.type == LUIType.warning
                    ? LUI.instance.warningColor
                    : LUI.instance.primaryColor);
    var useBorderRadius = widget.shape == LSwitchShape.circle
        ? min(useWidth, useHeight) / 2
        : widget.borderRadius ?? LStyle.borderRadius;

    var useDotWidth = useHeight - usePadding * 2;
    return LBox(
      margin: widget.margin,
      marginLeft: widget.marginLeft,
      marginRight: widget.marginRight,
      marginTop: widget.marginTop,
      marginBottom: widget.marginBottom,
      marginHorizontal: widget.marginHorizontal,
      marginVertical: widget.marginVertical,
      onTap: handleTap,
      width: useWidth,
      height: useHeight,
      backgroundColor: LUI.instance.backgroundColor
          .withOpacity(widget.disabled == true ? 0.5 : 1.0),
      borderRadius: [useBorderRadius],
      child: Stack(children: [
        LBox(
          width: useWidth,
          height: useHeight,
          fontSize: useHeight / 3 * 2,
          textAlign: TextAlign.right,
          color: Colors.white,
          paddingRight: useBorderRadius * 0.6,
          child: widget.inactiveText,
        ),
        FadeTransition(
          opacity: bgAnimation,
          child: LBox(
            width: useWidth,
            height: useHeight,
            backgroundColor: useColor,
            borderRadius: [useBorderRadius],
            color: Colors.white,
            fontSize: useHeight / 3 * 2,
            paddingLeft: useBorderRadius * 0.6,
            child: widget.activeText,
          ),
        ),
        Positioned(
            left: useLeft,
            child: LBox(
              width: useDotWidth,
              height: useDotWidth,
              margin: [usePadding],
              backgroundColor:
                  Colors.white.withOpacity(widget.disabled == true ? 0.7 : 1.0),
              borderRadius: [useBorderRadius],
            ))
      ]),
    );
  }
}
